#ifndef _CARDHOLDER_API_H_
#define _CARDHOLDER_API_H_

#include <config.h>
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>

// 蓝牙虚拟卡激活有效期 - 10min
#define VIRUAL_CARD_ACTIVATION_EFFECTIVE_TIME               (10 * 60)

// 用户名长度
#define CARDHOLDER_USER_NAME_LENGTH                         (USER_NAME_LENGTH)
// 虚拟值
#define VIRTUAL_VALUE                                       (PROTOCOL_DUMMY_CODING)

// 最小使用次数
#define MIX_NUMBER_OF_USE                                   (1ul)
// 最大使用次数
#define MAX_NUMBER_OF_USE                                   (100ul)
// 不限使用次数
#define USE_UNLIMITED_TIMES                                 (PROTOCOL_DUMMY_CODING)

// 单用户可分配密钥上限
#define MAX_NUMBER_OF_KEYS_CARRIED_BY_SINGLE_USER           (6ul)

/**
 * @brief 定义持卡人操作状态
 *
 */
typedef enum
{
  DELETE_FAILED,                    // 删除失败
  USER_NO_FOUND,                    // 用户未找到
  ENTRY_FAILURE,                    // 录入失败
  OPERATION_ERROR,                  // 操作失败
  CARD_HOLDER_FULL,                 // 持卡人已满
  UNKNOWN_KEY_TYPE,                 // 未知密钥类型
  KEY_ALREADY_EXISTS,               // 密钥已存在
  CARDHOLDER_DISABLED,              // 持卡人禁用
  RECORD_SUCCESSFULLY,              // 录入成功
  DELETED_SUCCESSFULLY,             // 删除成功
  AUTHENTICATION_SUCCESS,           // 鉴权成功
  AUTHENTICATION_FAILURE,           // 鉴权失败
  NOT_IN_THE_ALLOWED_TIME,          // 不在允许的时间内
  UNKNOWN_CARDHOLDER_STATUS,        // 未知持卡人状态
  OVER_OF_SINGLE_USER_REGISTER_KEY, // 超过单用户注册数量
} CardholderCommandResult_t;

/**
 * @brief 定义密钥状态
 *
 */
typedef enum
{
  NORMAL_USE    = 0x10, // 正常使用
  BLACKLIST_KEY = 0x11, // 黑名单密钥
} UserState_t;

/**
 * @brief 定义鉴权类型
 *
 */
typedef enum
{
  CARD_AUTHENTICATION                   = 0x11, // 卡片
  PASSWORD_AUTHENTICATION               = 0x12, // 密码
  QRCODE_AUTHENTICATION                 = 0x13, // 二维码
  FINGER_PRINTF_AUTHENTICATION          = 0x14, // 指纹
  FACE_ID_AUTHENTICATION                = 0x15, // 人脸特征值
  COMMAND_REMOTE_AUTHENTICATION         = 0x16, // 命令开锁
  BLUETOOTH_VIRTUAL_CARD_AUTHENTICATION = 0x17, // 蓝牙虚拟卡
} AuthenticationType_t;

#pragma pack(push, 1)

/**
 * @brief 描述时间区域格式
 *
 */
typedef struct
{
  uint8_t StartHour;   // 开始时
  uint8_t StartMinute; // 开始分
  uint8_t EndHour;     // 结束时
  uint8_t EndMinute;   // 结束分
} TimeCycle_t;

/**
 * @brief 时间戳转换
 *
 */
typedef union
{
  uint32_t BasicCycle;   // 基本周期
  TimeCycle_t TimeCycle; // 周期时间段
} CycleUnion_t;

/**
 * @brief 定义用户信息
 *
 */
typedef struct
{
  uint8_t Status;                     // 状态
  uint8_t NumberOfKey;                // 密钥数量
  uint8_t UserName[USER_NAME_LENGTH]; // 用户名称
} UserInformation_t;

/**
 * @brief 定义密钥信息
 *
 */
typedef struct
{
  uint8_t Count;                                             // 次数
  uint32_t KeyToken;                                         // 唯一编码
  uint8_t AuthenticationType;                                // 密钥类型
  uint8_t AuthenticationKey[USER_AUTHENTICATION_KEY_LENGTH]; // 鉴权密钥

  uint8_t Date;                            // 日期
  uint32_t EndTimestamp;                   // 结束时间
  uint32_t StartTimestamp;                 // 开始时间
  CycleUnion_t TimePeriod[MAX_TIME_SLOTS]; // 使用时间段
} KeyInformation_t;

/**
 * @brief 定义持卡人信息
 *
 */
typedef struct __attribute__((aligned(4)))
{
  UserInformation_t UserInformation;
  KeyInformation_t KeyInformation[MAX_NUMBER_OF_KEYS_CARRIED_BY_SINGLE_USER];
} CardholderInformation_t;

#pragma pack(pop)

/**
 * @brief 查找空闲的持卡人目录
 *
 * @param pCatalogueIdOut - 目录编码
 * @return bool           - 查找状态（true：成功 false：失败）
 */
extern bool FindEmptyCardholderCatalogues(uint8_t *pCatalogueIdOut);

/**
 * @brief 查找用户
 *
 * @param pUserNameIn     - 用户名
 * @param pListIdOut      - 用户列表
 * @param pInformationOut - 文件信息
 * @return bool           - 查找状态（true：成功 false：失败）
 */
extern bool FindCardholder(const uint8_t *pUserNameIn, uint8_t *pListIdOut, CardholderInformation_t *pInformationOut);

/**
 * @brief 初始化持卡人目录
 *
 */
extern void InitialiseCardholderDirectory(void);

/**
 * @brief 查询持卡人是否存在
 *
 * @param KeyType         - 密钥类型
 * @param pUserNameIn     - 用户名
 * @param pKeyValueIn     - 密钥
 * @param pInformationOut - 查询成功返回密钥归属信息
 * @return bool           - 查询状态（true：成功 false：失败）
 */
extern bool QueryIfTheKeyAlreadyExists(const uint8_t KeyType, const uint8_t *pUserNameIn, const void *pKeyValueIn, CardholderInformation_t *pInformationOut);

/**
 * @brief 查询对应用户的密钥数量
 *
 * @param pUserName - 用户名
 * @return uint16_t - 密钥数量
 */
extern uint16_t QueryTheNumberOfCorrespondingUserKeys(const uint8_t *pUserName);

/**
 * @brief 获取目标目录的持卡人信息
 *
 * @param CatalogueId     - 目录编码
 * @param pInformationOut - 持卡人信息
 * @return bool           - 获取状态（true：成功 false：失败）
 */
extern bool ObtainingCardholderInformationForTargetCatalogue(const uint8_t CatalogueId, CardholderInformation_t *pInformationOut);

/**
 * @brief 获取已注册持卡人序列号
 *
 * @param pSerialNumberOut - 已注册持卡人序列号
 * @return uint8_t         - 已注册持卡人数量
 */
extern uint8_t GetRegisteredCardholderSerialNumber(uint8_t *pSerialNumberOut);

/**
 * @brief 获取用户密钥信息
 *
 * @param pUserNameIn     - 用户名
 * @param pInformationOut - 用户信息
 * @return bool           - 获取状态（true：成功 false：失败）
 */
extern bool GetUserKeyInformation(const uint8_t *pUserNameIn, CardholderInformation_t *pInformationOut);

/**
 * @brief 删除持卡人
 *
 * @param KeyType                    - 密钥类型
 * @param pUserName                  - 用户名
 * @param pKeyValueIn                - 密钥
 * @return CardholderCommandResult_t - 命令执行结果
 */
extern CardholderCommandResult_t DeleteCardholders(const uint8_t KeyType, const uint8_t *pUserName, const void *pKeyValueIn);

/**
 * @brief 新增持卡人
 *
 * @param pUserNameIn                - 用户名
 * @param pKeyInformationIn          - 密钥权限信息
 * @return CardholderCommandResult_t - 命令执行结果
 */
extern CardholderCommandResult_t NewCardholders(const uint8_t *pUserNameIn, KeyInformation_t *pKeyInformationIn);

/**
 * @brief 修改持卡人信息
 *
 * @param pUserNameIn                - 用户名
 * @param UserStatus                 - 状态
 * @param pKeyInformationIn          - 密钥类型
 * @return CardholderCommandResult_t - 命令执行结果
 */
extern CardholderCommandResult_t ModifyCardholderInformation(const uint8_t *pUserNameIn, const uint8_t UserStatus, KeyInformation_t *pKeyInformationIn);

/**
 * @brief 验证键入密钥有效性
 *
 * @param KeyType                    - 密钥类型
 * @param pKeyValueIn                - 密钥
 * @param KeyLength                  - 密钥长度
 * @param pInformationOut            - 鉴权成功返回密钥归属信息
 * @return CardholderCommandResult_t - 命令执行结果
 */
extern CardholderCommandResult_t VerifyTheValidityOfTheTypedKey(const uint8_t KeyType, const void *pKeyValueIn, uint8_t KeyLength, KeyInformation_t *pInformationOut);

/**
 * @brief 验证蓝牙虚拟卡有效性
 *
 * @param pUserNameIn                - 用户名
 * @param ValidityPeriod             - 授权时间
 * @param pKeyInformationIn          - 密钥信息
 * @return CardholderCommandResult_t - 命令执行结果
 */
extern CardholderCommandResult_t BluetoothVirtualCardAuthentication(uint8_t *pUserNameIn, uint32_t ValidityPeriod, KeyInformation_t *pKeyInformationIn);

#endif
